﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using NUnit.Framework;

namespace Cloak.Reflection
{
	[TestFixture]
	public class ReflectFixture
	{
		#region Properties
		/// <summary>
		/// The flags which indicate a public static member
		/// </summary>
		private static BindingFlags StaticFlags
		{
			get { return BindingFlags.Public | BindingFlags.Static; }
		}

		/// <summary>
		/// The flags which indicate a public instance member
		/// </summary>
		private static BindingFlags InstanceFlags
		{
			get { return BindingFlags.Public | BindingFlags.Instance; }
		}
		#endregion

		#region Action
		[Test]
		public void StaticAction0Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticAction0Args", StaticFlags),
				Reflect.Action(Target.StaticAction0Args));
		}

		[Test]
		public void StaticAction1Arg()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticAction1Arg", StaticFlags),
				Reflect.Action<int>(Target.StaticAction1Arg));
		}

		[Test]
		public void StaticAction2Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticAction2Args", StaticFlags),
				Reflect.Action<int, int>(Target.StaticAction2Args));
		}

		[Test]
		public void StaticAction3Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticAction3Args", StaticFlags),
				Reflect.Action<int, int, int>(Target.StaticAction3Args));
		}

		[Test]
		public void StaticAction4Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticAction4Args", StaticFlags),
				Reflect.Action<int, int, int, int>(Target.StaticAction4Args));
		}

		[Test]
		public void Action0Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Action0Args", InstanceFlags),
				Reflect.Action(new Target().Action0Args));
		}

		[Test]
		public void Action1Arg()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Action1Arg", InstanceFlags),
				Reflect.Action<int>(new Target().Action1Arg));
		}

		[Test]
		public void Action2Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Action2Args", InstanceFlags),
				Reflect.Action<int, int>(new Target().Action2Args));
		}

		[Test]
		public void Action3Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Action3Args", InstanceFlags),
				Reflect.Action<int, int, int>(new Target().Action3Args));
		}

		[Test]
		public void Action4Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Action4Args", InstanceFlags),
				Reflect.Action<int, int, int, int>(new Target().Action4Args));
		}
		#endregion

		#region Func
		[Test]
		public void StaticFunc0Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticFunc0Args", StaticFlags),
				Reflect.Func<int>(Target.StaticFunc0Args));
		}

		[Test]
		public void StaticFunc1Arg()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticFunc1Arg", StaticFlags),
				Reflect.Func<int, int>(Target.StaticFunc1Arg));
		}

		[Test]
		public void StaticFunc2Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticFunc2Args", StaticFlags),
				Reflect.Func<int, int, int>(Target.StaticFunc2Args));
		}

		[Test]
		public void StaticFunc3Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticFunc3Args", StaticFlags),
				Reflect.Func<int, int, int, int>(Target.StaticFunc3Args));
		}

		[Test]
		public void StaticFunc4Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("StaticFunc4Args", StaticFlags),
				Reflect.Func<int, int, int, int, int>(Target.StaticFunc4Args));
		}

		[Test]
		public void Func0Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Func0Args", InstanceFlags),
				Reflect.Func<int>(new Target().Func0Args));
		}

		[Test]
		public void Func1Arg()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Func1Arg", InstanceFlags),
				Reflect.Func<int, int>(new Target().Func1Arg));
		}

		[Test]
		public void Func2Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Func2Args", InstanceFlags),
				Reflect.Func<int, int, int>(new Target().Func2Args));
		}

		[Test]
		public void Func3Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Func3Args", InstanceFlags),
				Reflect.Func<int, int, int, int>(new Target().Func3Args));
		}

		[Test]
		public void Func4Args()
		{
			Assert.AreEqual(
				typeof(Target).GetMethod("Func4Args", InstanceFlags),
				Reflect.Func<int, int, int, int, int>(new Target().Func4Args));
		}
		#endregion

		#region Field
		[Test]
		public void StaticFieldAsMember()
		{
			Assert.AreEqual(
				typeof(Target).GetField("StaticField", StaticFlags),
				Reflect.Member(() => Target.StaticField));
		}

		[Test]
		public void StaticField()
		{
			Assert.AreEqual(
				typeof(Target).GetField("StaticField", StaticFlags),
				Reflect.Field(() => Target.StaticField));
		}

		[Test]
		public void FieldAsMember()
		{
			Assert.AreEqual(
				typeof(Target).GetField("Field", InstanceFlags),
				Reflect.Member((Target r) => r.Field));
		}

		[Test]
		public void Field()
		{
			Assert.AreEqual(
				typeof(Target).GetField("Field", InstanceFlags),
				Reflect.Field((Target r) => r.Field));
		}
		#endregion

		#region Property
		[Test]
		public void StaticPropertyAsMember()
		{
			Assert.AreEqual(
				typeof(Target).GetProperty("StaticProperty", StaticFlags),
				Reflect.Member(() => Target.StaticProperty));
		}

		[Test]
		public void StaticProperty()
		{
			Assert.AreEqual(
				typeof(Target).GetProperty("StaticProperty", StaticFlags),
				Reflect.Property(() => Target.StaticProperty));
		}

		[Test]
		public void PropertyAsMember()
		{
			Assert.AreEqual(
				typeof(Target).GetProperty("Property", InstanceFlags),
				Reflect.Member((Target r) => r.Property));
		}

		[Test]
		public void Property()
		{
			Assert.AreEqual(
				typeof(Target).GetProperty("Property", InstanceFlags),
				Reflect.Property((Target r) => r.Property));
		}
		#endregion

		#region Constructor
		[Test]
		public void Constructor0Args()
		{
			Assert.AreEqual(
				typeof(Target).GetConstructor(Type.EmptyTypes),
				Reflect.Constructor(() => new Target()));
		}

		[Test]
		public void Constructor1Arg()
		{
			Assert.AreEqual(
				typeof(Target).GetConstructor(new Type[] { typeof(int) }),
				Reflect.Constructor((int a) => new Target(a)));
		}

		[Test]
		public void Constructor2Args()
		{
			Assert.AreEqual(
				typeof(Target).GetConstructor(new Type[] { typeof(int), typeof(int) }),
				Reflect.Constructor((int a, int b) => new Target(a, b)));
		}

		[Test]
		public void Constructor3Args()
		{
			Assert.AreEqual(
				typeof(Target).GetConstructor(new Type[] { typeof(int), typeof(int) , typeof(int) }),
				Reflect.Constructor((int a, int b, int c) => new Target(a, b, c)));
		}

		[Test]
		public void Constructor4Args()
		{
			Assert.AreEqual(
				typeof(Target).GetConstructor(new Type[] { typeof(int), typeof(int), typeof(int), typeof(int) }),
				Reflect.Constructor((int a, int b, int c, int d) => new Target(a, b, c, d)));
		}
		#endregion
	}
}